﻿using DLog.Access.Context;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace DLog.Access.Repository
{
    public class Repository<T> : IRepository<T> where T : class
    {
        protected DLogContext Context;
        protected IDbSet<T> dbSet;

        public Repository()
        {
            Context = new DLogContext();
            dbSet = Context.Set<T>();
        }

        public Repository(DLogContext context)
        {
            Context = context;
            dbSet = Context.Set<T>();
        }

        public void Dispose()
        {
            if (Context != null)
                Context.Dispose();
        }

        public virtual IQueryable<T> All()
        {
            return dbSet.AsQueryable();
        }

        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> predicate)
        {
            return dbSet.Where(predicate).AsQueryable<T>();
        }

        //             IQueryable<T> Filter<Key>(Expression<Func<T, bool>> filter, out int total, int index = 0, int size = 50);
        public virtual IQueryable<T> Filter(Expression<Func<T, bool>> filter, out int total, int index = 0, int size = 50)
        {
            int skipCount = index * size;
            var _resetSet = filter != null ? dbSet.Where(filter).AsQueryable() : dbSet.AsQueryable();
            _resetSet = skipCount == 0 ? _resetSet.Take(size) : _resetSet.Skip(skipCount).Take(size);
            total = _resetSet.Count();
            return _resetSet.AsQueryable();
        }

        public bool Contains(Expression<Func<T, bool>> predicate)
        {
            return dbSet.Count(predicate) > 0;
        }

        public virtual T Find(params object[] keys)
        {
            return dbSet.Find(keys);
        }

        public virtual T Find(Expression<Func<T, bool>> predicate)
        {
            return dbSet.FirstOrDefault(predicate);
        }

        public virtual T Create(T t)
        {
            var newEntry = dbSet.Add(t);
            Context.SaveChanges();
            return newEntry;
        }

        public virtual int Insert(T t)
        {
            var newEntry = dbSet.Add(t);
            return Context.SaveChanges();
        }

        public virtual int Count
        {
            get
            {
                return dbSet.Count();
            }
        }

        public virtual int Delete(T t)
        {
            dbSet.Remove(t);
            return Context.SaveChanges();
        }

        public virtual int Update(T t)
        {
            var entry = Context.Entry(t);
            dbSet.Attach(t);
            entry.State = EntityState.Modified;
            return Context.SaveChanges();
        }

        public virtual int Delete(Expression<Func<T, bool>> predicate)
        {
            var objects = Filter(predicate);
            foreach (var obj in objects)
                dbSet.Remove(obj);
            return Context.SaveChanges();
        }
    }
}
